home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 June
/
EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso
/
earcd
/
c-lang
/
vbcc.lha
/
vbcc
/
parse_expr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-15
|
23KB
|
749 lines
/* $VER: vbcc (parse_expr.c) V0.3 */
#include "vbc.h"
np expression(void)
/* Komma-Ausdruecke */
{
np left,right,new;
left=assignment_expression();
if(!left->flags) return(0);
killsp();
while(*s==','){
s++;
killsp();
right=assignment_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->ntyp=0;
new->flags=KOMMA;
left=new;
killsp();
}
return(left);
}
np assignment_expression(void)
/* Zuweisungsausdruecke */
{
np left,new;int c=0;
left=conditional_expression();
killsp();
if(*s!='='&&*(s+1)!='='&&*(s+2)!='=') return(left);
if(*s=='=') {c=ASSIGN;s++;} else
{if(*s=='*'&&*(s+1)=='=') {c=ASSIGNMULT;s+=2;} else
{if(*s=='/'&&*(s+1)=='=') {c=ASSIGNDIV;s+=2;} else
{if(*s=='%'&&*(s+1)=='=') {c=ASSIGNMOD;s+=2;} else
{if(*s=='+'&&*(s+1)=='=') {c=ASSIGNADD;s+=2;} else
{if(*s=='-'&&*(s+1)=='=') {c=ASSIGNSUB;s+=2;} else
{if(*s=='&'&&*(s+1)=='=') {c=ASSIGNAND;s+=2;} else
{if(*s=='^'&&*(s+1)=='=') {c=ASSIGNXOR;s+=2;} else
{if(*s=='|'&&*(s+1)=='=') {c=ASSIGNOR;s+=2;} else
{if(*s=='<'&&*(s+1)=='<') {c=ASSIGNLSHIFT;s+=3;}else
{if(*s=='>'&&*(s+1)=='>') {c=ASSIGNRSHIFT;s+=3;}else {return(left);}
}}}}}}}}}}
new=(np)mymalloc(NODES);
new->left=left;
new->ntyp=0;
if(c==ASSIGN){
new->right=assignment_expression();
new->flags=ASSIGN;
}else{
/* ASSIGNOP(a,b)->ASSIGN(a,OP(a,b)) */
new->flags=ASSIGNADD; /* nur zum Merken, dass nur einmal */
/* ausgewertet werden darf */
new->right=(np)mymalloc(NODES);
new->right->left=left;
new->right->right=assignment_expression();
new->right->ntyp=0;
if(c==ASSIGNMULT) new->right->flags=MULT;
if(c==ASSIGNDIV) new->right->flags=DIV;
if(c==ASSIGNMOD) new->right->flags=MOD;
if(c==ASSIGNADD) new->right->flags=ADD;
if(c==ASSIGNSUB) new->right->flags=SUB;
if(c==ASSIGNAND) new->right->flags=AND;
if(c==ASSIGNXOR) new->right->flags=XOR;
if(c==ASSIGNOR) new->right->flags=OR;
if(c==ASSIGNLSHIFT) new->right->flags=LSHIFT;
if(c==ASSIGNRSHIFT) new->right->flags=RSHIFT;
}
return(new);
}
np conditional_expression(void)
/* Erledigt ? : momentan noch nicht implementiert */
{
np left,new;
left=logical_or_expression();
killsp();
if(*s=='?'){ /* hier ein while ? */
s++;killsp();
new=(np)mymalloc(NODES);
new->flags=COND;
new->ntyp=0;
new->left=left;
new->right=(np)mymalloc(NODES);
new->right->flags=COLON;
new->right->ntyp=0;
new->right->left=expression();
killsp();
if(*s==':'){s++;killsp();} else error(70);
new->right->right=conditional_expression();
left=new;
killsp();
}
return(left);
}
np logical_or_expression(void)
/* Erledigt || */
{
np left,right,new;
left=logical_and_expression();
killsp();
while(*s=='|'&&*(s+1)=='|'){
s+=2;
killsp();
right=logical_and_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=LOR;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np logical_and_expression(void)
/* Erledigt && */
{
np left,right,new;
left=inclusive_or_expression();
killsp();
while(*s=='&'&&*(s+1)=='&'){
s+=2;
killsp();
right=inclusive_or_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=LAND;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np inclusive_or_expression(void)
/* Erledigt | */
{
np left,right,new;
left=exclusive_or_expression();
killsp();
while(*s=='|'&&*(s+1)!='|'&&*(s+1)!='='){
s++;
killsp();
right=exclusive_or_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=OR;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np exclusive_or_expression(void)
/* Erledigt ^ */
{
np left,right,new;
left=and_expression();
killsp();
while(*s=='^'&&*(s+1)!='='){
s++;
killsp();
right=and_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=XOR;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np and_expression(void)
/* Erledigt & */
{
np left,right,new;
left=equality_expression();
killsp();
while(*s=='&'&&*(s+1)!='&'&&*(s+1)!='='){
s++;
killsp();
right=equality_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=AND;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np equality_expression(void)
/* Erledigt == und != */
{
np left,right,new;int c;
left=relational_expression();
killsp();
while((*s=='='||*s=='!')&&*(s+1)=='='){
if(*s=='!') c=INEQUAL; else c=EQUAL;
s+=2;
killsp();
right=relational_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np relational_expression(void)
/* Erledigt <,>,<=,>= */
{
np left,right,new;int c;
left=shift_expression();
killsp();
while((*s=='<'&&*(s+1)!='<')||(*s=='>'&&*(s+1)!='>')){
if(*s++=='<'){
if(*s=='='){s++;c=LESSEQ;}else c=LESS;
}else{
if(*s=='='){s++;c=GREATEREQ;}else c=GREATER;
}
killsp();
right=shift_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np shift_expression(void)
/* Erledigt <<,>> */
{
np left,right,new;int c;
left=additive_expression();
killsp();
while((*s=='<'&&*(s+1)=='<'&&*(s+2)!='=')||(*s=='>'&&*(s+1)=='>'&&*(s+2)!='=')){
if(*s=='<') c=LSHIFT; else c=RSHIFT;
s+=2;
killsp();
right=additive_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np additive_expression(void)
/* Erledigt +,- */
{
np left,right,new;int c;
left=multiplicative_expression();
killsp();
while((*s=='+'||*s=='-')&&*(s+1)!='='){
if(*s++=='+') c=ADD; else c=SUB;
killsp();
right=multiplicative_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np multiplicative_expression(void)
/* Erledigt *,/,% */
{
np left,right,new;int c;
left=cast_expression();
killsp();
while((*s=='*'||*s=='/'||*s=='%')&&*(s+1)!='='){
if(*s=='*') c=MULT; else {if(*s=='/') c=DIV; else c=MOD;}
s++;
killsp();
right=cast_expression();
new=(np)mymalloc(NODES);
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return(left);
}
np cast_expression(void)
/* Erledigt (typ) */
{
np new;char *imerk,buff[MAXI];
killsp();
if(*s!='('||!declaration(1)) return(unary_expression());
s++;killsp();
new=(np)mymalloc(NODES);
new->flags=CAST;
new->right=0;
imerk=ident;ident=buff;
new->ntyp=declarator(declaration_specifiers());
ident=imerk;
killsp();
if(*s!=')') error(59); else s++;
new->left=cast_expression();
return(new);
}
np unary_expression(void)
/* Erledigt !,~,++,--,+,-,*,&,sizeof */
{
np new;char *merk=s,buff[MAXI];int done=0;
killsp();
if((*s!='s'&&*s!='+'&&*s!='-'&&*s!='&'&&*s!='*'&&*s!='~'&&*s!='!')||*(s+1)=='=') return(postfix_expression());
if(*s=='s'){
merk=s;cpbez(buff);s=merk;
if(strcmp("sizeof",buff)) return(postfix_expression());
else{
s+=6;killsp();
new=(np)mymalloc(NODES);
new->flags=CEXPR;
new->ntyp=(struct Typ *)mymalloc(TYPS);
new->ntyp->flags=UNSIGNED|LONG;
new->ntyp->next=0;
new->right=0;
new->left=0;
if(*s=='('&&declaration(1)){
struct Typ *t;
s++;killsp();
merk=ident;ident=buff;
t=declarator(declaration_specifiers());
if(type_uncomplete(t)) error(176);
ident=merk;
new->val.vulong=zl2zul(l2zl((long)szof(t)));
freetyp(t);
killsp();
if(*s!=')') error(59); else s++;
}else{
np tree;
killsp();
tree=unary_expression();
if(!tree||!type_expression(tree)){
new->val.vulong=zl2zul(l2zl(0L));
error(73);
}else{
if(type_uncomplete(tree->ntyp)) error(176);
new->val.vulong=zl2zul(l2zl((long)szof(tree->ntyp)));
}
if(tree) free_expression(tree);killsp();
}
return(new);
}
}
new=(np)mymalloc(NODES);
new->right=0;
new->ntyp=0;
if(*s=='+'&&!done)
if(*(s+1)=='+'){
s+=2;done=1;
new->left=unary_expression();
new->flags=PREINC;
}else{
s++;free(new);
return(cast_expression());
}
if(*s=='-'&&!done){
done=1;
if(*(s+1)=='-'){
s+=2;
new->left=unary_expression();
new->flags=PREDEC;
}else{
s++;
new->left=cast_expression();
new->flags=MINUS;
}
}
if(*s=='&'&&!done){
s++;done=1;
new->left=cast_expression();
new->flags=ADDRESS;
}
if(*s=='*'&&!done){
s++;done=1;
new->left=cast_expression();
new->flags=CONTENT;
}
if(*s=='~'&&!done){
s++;done=1;
new->left=cast_expression();
new->flags=KOMPLEMENT;
}
if(*s=='!'&&!done){
s++;done=1;
new->left=cast_expression();
new->flags=NEGATION;
}
new->right=0;
new->ntyp=0;
return(new);
}
np postfix_expression(void)
/* Erledigt [],(),.,->,++,-- */
{
np new,left;int done;
left=primary_expression();
killsp();
while(*s=='['||*s=='('||*s=='.'||(*s=='-'&&((*(s+1)=='-')||(*(s+1)=='>')))
||(*s=='+'&&*(s+1)=='+')){
done=0;
new=(np)mymalloc(NODES);
new->ntyp=0;
new->right=0;
new->left=left;
if(*s=='-'){
s++;done=1;
if(*s=='-'){
s++;
new->flags=POSTDEC;
}else{
s++; killsp();
new->flags=DSTRUCT;
new->right=identifier_expression();
new->right->flags=MEMBER;
new->left=(np)mymalloc(NODES);
new->left->ntyp=0;
new->left->left=left;
new->left->right=0;
new->left->flags=CONTENT;
}
}
if(*s=='['&&!done){
s++; killsp();done=1;
new->flags=CONTENT;
new->left=(np)mymalloc(NODES);
new->left->flags=ADD;
new->left->ntyp=0;
new->left->left=left;
new->left->right=expression();
killsp();
if(*s!=']') error(62); else s++;
}
if(*s=='+'&&!done){
s+=2;done=1;
new->flags=POSTINC;
}
if(*s=='.'&&!done){
s++;killsp();done=1;
new->right=identifier_expression();
new->flags=DSTRUCT;
new->right->flags=MEMBER;
}
if(*s=='('&&!done){
struct argument_list *al,*first_alist=0,*last_alist=0;np n;
s++;killsp();done=1;
new->flags=CALL;
new->right=0;
while(*s!=')'){
n=assignment_expression();
al=(struct argument_list *)mymalloc(sizeof(struct argument_list));
al->arg=n;al->next=0;
if(last_alist){
last_alist->next=al;
last_alist=al;
}else{
last_alist=first_alist=al;
}
killsp();
if(*s==',') {s++;killsp();} /* hier noch strenger */
}
new->alist=first_alist;
if(*s!=')') error(59); else s++;
}
left=new;
killsp();
}
return(left);
}
np primary_expression(void)
/* Hier fehlt noch allerhand */
{
np new;
if((*s>='0'&&*s<='9')||*s=='.') return(constant_expression());
if(*s=='\"'||*s=='\''||(*s=='L'&&(*(s+1)=='\''||*(s+1)=='\"'))) return(string_expression());
if(*s=='('){
s++;killsp();
new=expression();
killsp();
if(*s!=')') error(59); else s++;
return(new);
}
return(identifier_expression());
}
np string_expression(void)
/* Gibt Zeiger auf string oder Zeichenkonstante zurueck */
{
np new; char f,string[MAXINPUT],*p;int flag,val;zlong zl;
if(*s=='L') s++; /* Noch keine erweiterten Zeichen */
p=string;f=*s++;
while(1){
while(*s!=f&&p<&string[MAXINPUT-1]){
if(*s=='\\'){
s++;
if(*s=='\\'){*p++='\\';s++;continue;}
if(*s=='n'){*p++='\n';s++;continue;}
if(*s=='t'){*p++='\t';s++;continue;}
if(*s=='r'){*p++='\r';s++;continue;}
if(*s=='v'){*p++='\v';s++;continue;}
if(*s=='b'){*p++='\b';s++;continue;}
if(*s=='f'){*p++='\f';s++;continue;}
if(*s=='a'){*p++='\a';s++;continue;}
if(*s=='\?'){*p++='\?';s++;continue;}
if(*s=='\''){*p++='\'';s++;continue;}
if(*s=='\"'){*p++='\"';s++;continue;}
flag=val=0;
while(*s>='0'&&*s<='7'&&flag<3){
val=val*8+*s-'0';
s++;flag++;
}
if(flag){*p++=val;continue;}
if(*s=='x'){
s++;val=0;
while((*s>='0'&&*s<='9')||(*s>='a'&&*s<='f')||(*s>='A'&&*s<='F')){
val=val*16;
if(*s>='0'&&*s<='9') val+=*s-'0';
if(*s>='a'&&*s<='f') val+=*s-'a'+10;
if(*s>='A'&&*s<='F') val+=*s-'A'+10;
s++;
}
*p++=val;continue;
}
error(71);
}
*p++=*s++;
}
if(*s!=f) error(74); else s++;
killsp();
if(f!='\"'||*s!=f) break; else s++;
}
*p=0;
new=(np)mymalloc(NODES);
new->ntyp=(struct Typ *)mymalloc(TYPS);
if(f=='\"'){
struct const_list *cl,**prev;int i;
new->ntyp->flags=ARRAY;
new->ntyp->size=p-string+1;
new->ntyp->next=(struct Typ *)mymalloc(TYPS);
new->ntyp->next->flags=STRINGCONST|CHAR;
new->ntyp->next->next=0;
new->flags=STRING;
prev=(struct const_list **)&new->identifier;
for(i=0;i<p-string+1;i++){
cl=(struct const_list *)mymalloc(CLS);
cl->next=0;
cl->tree=0;
cl->other=(struct const_list *)mymalloc(CLS);
cl->other->next=cl->other->other=0;
cl->other->tree=0;
cl->other->val.vchar=zl2zc(l2zl((long)string[i]));
*prev=cl;
prev=&cl->next;
}
/* new->identifier=add_identifier(string,p-string);*/
new->val.vlong=l2zl(0L);
}else{
new->ntyp->flags=CONST|INT;
new->ntyp->next=0;
new->flags=CEXPR;
zl=l2zl(0L);
p--;
if(p>string) error(72);
while(p>=string){
/* zl=zl<<CHAR_BIT+*p */
zl=zllshift(zl,l2zl((long)CHAR_BIT));
zl=zladd(zl,l2zl((long)*p));
new->val.vint=zl2zi(zl);
p--;
}
}
new->left=new->right=0;
return(new);
}
np constant_expression(void)
/* Gibt Zeiger auf erzeugt Struktur fuer Konstante zurueck */
/* Es werden die Werte aus <limits.h> benutzt. */
{
np new; zdouble db;
zulong value,zbase,digit;unsigned long base=10,t;char *merk;
merk=s;
value=ul2zul(0L);
new=(np)mymalloc(NODES);
new->ntyp=(struct Typ *)mymalloc(TYPS);
new->ntyp->flags=0;
new->ntyp->next=0;
new->flags=CEXPR;
new->left=new->right=0;
new->sidefx=0;
if(*s=='0'){
s++;
if(*s=='x'||*s=='X'){s++;base=16;} else base=8;
}
zbase=ul2zul(base);
if(*s>='0'&&*s<='9') t=*s-'0'; else{
if(*s>='a'&&*s<='f') t=*s-'a'+10; else{
if(*s>='A'&&*s<='F') t=*s-'A'+10; else{t=20;}}}
while(t<base){
digit=ul2zul(t);
value=zuladd(zulmult(value,zbase),digit);
s++;
if(*s>='0'&&*s<='9') t=*s-'0'; else{
if(*s>='a'&&*s<='f') t=*s-'a'+10; else{
if(*s>='A'&&*s<='F') t=*s-'A'+10; else{t=20;}}}
}
while(*s=='u'||*s=='U'||*s=='l'||*s=='L'){
if(*s=='u'||*s=='U'){
if(zulleq(value,UINT_MAX)) new->ntyp->flags=UNSIGNED|INT;
else new->ntyp->flags=UNSIGNED|LONG;
}else{
if(zulleq(value,LONG_MAX)) new->ntyp->flags=LONG;
else new->ntyp->flags=UNSIGNED|LONG;
}
s++;
}
if(new->ntyp->flags==0){
if(base==10){
if(zulleq(value,INT_MAX)) new->ntyp->flags=INT; else{
if(zulleq(value,LONG_MAX)) new->ntyp->flags=LONG; else
new->ntyp->flags=UNSIGNED|LONG;}
}else{
if(zulleq(value,INT_MAX)) new->ntyp->flags=INT; else{
if(zulleq(value,UINT_MAX))new->ntyp->flags=UNSIGNED|INT; else{
if(zulleq(value,LONG_MAX))new->ntyp->flags=LONG; else
new->ntyp->flags=UNSIGNED|LONG;}}
}
}
if(*s=='.'||*s=='e'||*s=='E'){
/* Fliesskommakonstante, ignoriert vorher berechneten Wert, falls er */
/* nicht dezimal und nicht 0 war (da er dann oktal war) */
if(*merk=='0'&&!zuleq(value)){
value=ul2zul(0UL);zbase=ul2zul(10UL);
while(*merk>='0'&&*merk<='9'){
digit=ul2zul((unsigned long)(*merk-'0'));
value=zuladd(zulmult(value,zbase),digit);
merk++;
}
if(merk!=s) error(75);
}
db=zul2zd(value);
if(*s=='.'){
/* Teil hinter Kommastellen */
zdouble zquot,zbased,digit;
s++;
zbased=d2zd(10);zquot=d2zd(0.1);
while(*s>='0'&&*s<='9'){
digit=d2zd((double)(*s-'0'));
db=zdadd(db,zdmult(digit,zquot));
zquot=zddiv(zquot,zbased);
s++;
}
}
if(*s=='e'||*s=='E'){
/* Exponentialdarstellung */
int exp,vorz,i;zdouble zbased;
zbased=d2zd((double)10);
s++;
if(*s=='-'){
s++;vorz=-1;
}else{
vorz=1;if(*s=='+') s++;
}
exp=0;
while(*s>='0'&&*s<='9') exp=exp*10+*s++-'0';
for(i=0;i<exp;i++){
if(vorz>0) db=zdmult(db,zbased);
else db=zddiv(db,zbased);
}
}
new->ntyp->flags=DOUBLE;
if(*s=='f'||*s=='F'){
new->ntyp->flags=FLOAT;s++;
}else{
/* long double werden nicht unterstuetzt und sind==double :-( */
if(*s=='l'||*s=='L') s++;
}
}
if(new->ntyp->flags==FLOAT) new->val.vfloat=zd2zf(db);
if(new->ntyp->flags==DOUBLE) new->val.vdouble=db;
if(new->ntyp->flags==INT) new->val.vint=zl2zi(zul2zl(value));
if(new->ntyp->flags==(UNSIGNED|INT)) new->val.vuint=zul2zui(value);
if(new->ntyp->flags==LONG) new->val.vlong=zul2zl(value);
if(new->ntyp->flags==(UNSIGNED|LONG)) new->val.vulong=value;
return(new);
}
np identifier_expression(void)
/* Erzeugt Identifier mit Knoten */
{
np new;char buff[MAXI];
killsp();cpbez(buff);
new=(np)mymalloc(NODES);
new->flags=IDENTIFIER;
new->left=new->right=0;
new->identifier=add_identifier(buff,strlen(buff));
new->ntyp=0;
new->sidefx=0;
new->val.vlong=l2zl(0L);
if(new->identifier==empty) {error(76);new->flags=0;}
return(new);
}
void free_alist(struct argument_list *p)
/* Gibt argument_list inkl. expressions frei */
{
struct argument_list *merk;
while(p){
merk=p->next;
if(p->arg) free_expression(p->arg);
free(p);
p=merk;
}
}
void free_expression(np p)
/* Gibt expression mit allen Typen etc. frei */
{
if(!p) return;
if(p->flags==ASSIGNADD){
if(!p->right){ierror(0);return;}
if(p->right->left==p->left) p->left=0;
if(p->right->right==p->left) p->left=0;
}
if(p->flags==CALL&&p->alist) free_alist(p->alist);
if(p->ntyp) freetyp(p->ntyp);
if(p->left) free_expression(p->left);
if(p->right) free_expression(p->right);
free(p);
}